import * as THREE from 'three'
import Experience from '../class/Experience';
import { Line2 } from 'three/examples/jsm/lines/Line2'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { CreateLine, CreateNormalLine, CreateFly } from '../shape/Line'
import { CreateShape } from '../shape/Shape'
import { CreateTag, Create3DTag, CreateMarkTag } from '../shape/Tag'

import { EventEmitter } from 'events'

import { lishuiData } from '../data/lishuidata'
export default class Map extends EventEmitter {
    constructor() {
        super();
        this.experience = new Experience();
        this.fileLoader = this.experience.fileLoader;
        // 地图组
        this.group = new THREE.Group();

        // 地图线组
        this.lineMap = new THREE.Group();

        // 地图块组
        this.blockMap = new THREE.Group();

        // 地图名字组
        this.nameMap = new THREE.Group();
        this.name3DMap = new THREE.Group();

        // 地图标记组
        this.markGroup = new THREE.Group();

        // 地图线路
        this.lineGroup = new THREE.Group();

        // 飞线组
        this.flyGroup = new THREE.Group();
        // 整合所有子组
        this.group.add(this.lineMap);
        this.group.add(this.blockMap);
        // this.group.add(this.nameMap);
        this.group.add(this.name3DMap);
        this.group.add(this.markGroup);
        this.group.add(this.lineGroup);
        this.group.add(this.flyGroup);

        // this.canUpdate = false;
        this.experience.assets.on('ready', () => {
            this.items = this.experience.assets.items;
            console.log(this.items);
            this.createMap();
            this.createMark();

            // 根据线路创建飞线轨迹
            this.createLine();
            // this.canUpdate = true;
        })

        // 射线拾取地图块模型
        this.experience.utils.on('raycasterMove', event => {
            const result = this.experience.utils.rayChoose(event, this.blockMap.children); //射线拾取结果
            const markGroupResult = this.experience.utils.rayChoose(event, this.markGroup.children);
            if (result.length) {
                // console.log(result[0]);
            }

        })
        this.experience.utils.on('raycasterClick', event => {
            this.raycasterMark(event);
            this.raycasterLine(event);
        })
    }
    // 处理标记点点击时间
    raycasterMark(event) {
        const meshList = this.markGroup.children.filter(item => item.name === 'mark_down')
        const markGroupResult = this.experience.utils.rayChoose(event, meshList);
        if (markGroupResult.length) {
            const name = markGroupResult[0].object.stationName
            this.markGroup.traverse(item => {
                if (item.stationName === name) {
                    if (item.name !== 'mark_down') {
                        item.visible = !item.visible
                    }
                }
            })
        }
    }

    // 处理线条点击事件
    raycasterLine(event) {
        const meshList = this.lineGroup.children;
        const markGroupResult = this.experience.utils.rayChoose(event, meshList);
        if (markGroupResult.length) {
            const includes = markGroupResult[0].object.includes;
            const dblist = this.markGroup.children.filter(item => includes.includes(item.stationName) && item.name !== 'mark_down')
            const allShow = dblist.filter(item => item.visible)
            dblist.forEach(item => item.visible = allShow.length !== 4)
        }
    }
    createMap() {
        this.items['LiShuiGeoJson'].features.forEach((area) => {

            // 把"Polygon"和"MultiPolygon"的geometry.coordinates数据结构处理为一致
            if (area.geometry.type === "Polygon") area.geometry.coordinates = [area.geometry.coordinates];
            this.lineFun(area.geometry.coordinates)
            this.blockFun(area.geometry.coordinates)
            this.tagFun(area.properties)
            this.tag3DFun(area.properties)
        });
        this.group.rotateX(-Math.PI / 2);
        this.experience.box3.moveToCenter(this.group)
        this.group.position.y += 0.179
    }

    createLine() {
        const list = this.experience.data.lines;
        list.forEach(item => {
            const line = new CreateNormalLine(item);
            this.lineGroup.add(line);
            const fly = new CreateFly(line.points, line.color, line.includes)
            this.flyGroup.add(fly);
        })
        this.lineGroup.position.z += 0.002
        this.flyGroup.position.z += 0.002
        // console.log('========== 线条模型 ============');
        // console.log(this.lineGroup);
    }

    // 模型分开放入一个组 这样射线拾取的时候可以方便控制显示隐藏
    createMark() {
        const markUpGlb = this.items['markUpGlb']
        // const markUpGlb = this.initMarkModel()
        const markDownGlb = this.items['markDownGlb']
        const list = this.experience.data.stations;
        list.forEach(item => {
            const itemGlb = markUpGlb.clone();
            const dotGlb = markDownGlb.clone();
            const upMesh = this.initMarkModel(itemGlb, item.color, item.name)
            const dotMesh = this.initDotModel(dotGlb, item.color, item.name)
            upMesh.position.set(item.E, item.N, 0);
            dotMesh.position.set(item.E, item.N, 0);
            dotMesh.position.z += 0.02
            const nameMesh = new CreateMarkTag(item, this.items.Font)
            nameMesh.stationName = item.name
            upMesh.position.z += 0.008

            upMesh.visible = false
            nameMesh.visible = false
            this.markGroup.add(upMesh)
            this.markGroup.add(nameMesh)
            this.markGroup.add(dotMesh)
        })
        this.markGroup.position.z -= 0.01
        console.log(this.markGroup.children);

        // this.markGroup.visible = fa;se

    }

    // 改变克隆后的模型的属性
    initDotModel(markGlb, color = '#3963bc', name = '') {
        const mesh = markGlb.children.find((child) => child.name === "mark_down")

        // mesh.material = mesh.material.clone();
        // mesh.material.color = new THREE.Color(color)
        // mesh.stationName = name
        // // const downMaterial = new THREE.MeshBasicMaterial({ color });
        // mesh.rotateX(Math.PI / 2);
        // mesh.scale.multiplyScalar(0.1)
        // return mesh
        const material = new THREE.MeshStandardMaterial({
            color: new THREE.Color(color).multiplyScalar(1),
            // emissive:new THREE.Color(color).multiplyScalar(0.5),
            roughness: 0.9,
            metalness: 0,
            transparent: true,
            opacity: 1,
            depthWrite: true,
            // envMap:envMap,
        })

        // const material = new THREE.MeshBasicMaterial({ color });
        mesh.stationColor = color;
        mesh.stationName = name;
        mesh.material = material
        mesh.rotateX(Math.PI / 2);
        mesh.scale.multiplyScalar(0.02)
        return mesh
    }
    // 改变克隆后的模型的属性
    initMarkModel(markGlb, color = '#3963bc', name = '') {
        const markUpMesh = markGlb.children.find((child) => child.name === "mark_up")

        // 必须克隆材质 才能重新赋值颜色 否则认为材质共用
        markUpMesh.material = markUpMesh.material.clone();
        markUpMesh.material.color = new THREE.Color(color)
        markUpMesh.stationName = name
        // const downMaterial = new THREE.MeshBasicMaterial({ color });
        markUpMesh.rotateX(Math.PI / 2);
        markUpMesh.scale.multiplyScalar(0.04)
        return markUpMesh
    }

    // 生成地图的线框
    lineFun(coordinates) {
        coordinates.forEach(item => {
            const arr = [];  //边界线顶点坐标
            item[0].forEach(i => {
                arr.push(i[0], i[1], 0);
            });
            this.lineMap.add(new CreateLine(arr))
        })
        this.lineMap.position.z = 0.002
    }

    // 生成地图块
    blockFun(coordinates) {
        const shapeArr = [];
        coordinates.forEach(item => {
            const arr = [];
            item[0].forEach(i => arr.push(new THREE.Vector2(i[0], i[1])))
            const shape = new THREE.Shape(arr);
            shapeArr.push(shape);
        })
        this.blockMap.add(new CreateShape(shapeArr))
        this.blockMap.position.z = 0
    }

    // 生成文字
    tagFun(properties) {
        const mesh = new CreateTag(properties);
        this.nameMap.add(mesh)
    }

    // 生成3D文字
    tag3DFun(properties) {
        const mesh = new Create3DTag(properties, this.items.Font);
        this.name3DMap.add(mesh)
        this.name3DMap.position.z = 0.005
    }

    // 更新飞线位置
    update() {
        this.flyGroup.children.forEach(item => {
            if (item.index > item.indexMax) item.index = 0;
            item.index += 1;
            const newPoints = item.points.slice(item.index, item.index + item.number);
            const curve = new THREE.CatmullRomCurve3(newPoints, false, "catmullrom", 0);
            const newPoints2 = curve.getSpacedPoints(item.divider); //获取更多的点数
            item.geometry.setFromPoints(newPoints2);
        })
    }
}